[AWS Glue] S3バケットにある大量のファイルを圧縮して別のS3バケットに保存してみた
こんにちは、AWS事業本部の荒平(@0Air)です。
最近、S3バケットにある大量のファイルをなんとかしてZip化したいとの要望がありました。
大多数の方はLambdaを採用して済むケースが多いと思われますが、Lambdaを使わない方法を考えてみました。
概要
簡単な構成図はこちらです。
ファイル数・容量に振れ幅のあるログファイルなどを想定しているため、別バケットに保存することとしました。
Lambdaを採用しなかった背景
同じ構成はLambdaでも作ることができます。が、以下の理由から採用を見送りました。
- 一時ストレージは10GBまでに限られる
- 関数のタイムアウトは900秒が上限
- ファイル数が莫大だと、処理が終わらない可能性があります。その点、Glueは48時間まで動作をサポートします。
料金
今回の構成により、AWS Glue側で発生する料金は以下の通りです。 ※S3ストレージ料金等は別途かかります
課金項目 | 料金 |
---|---|
AWS Glue Jobrun | Python Shell ジョブごとに、DPU 時間あたり 0.44USD が 1 秒単位で課金され、最小 1 分 |
AWS Glue Request | 最初の 100 万回のリクエストは毎月無料。月に 100 万回を超えると、100 万回のリクエストあたり 1.00USD |
AWS Glue Storage | 最初の 100 万個のオブジェクトの保存は無料。月に 100 万個を超えると、10 万個のオブジェクトの保存あたり 1.00USD |
なお、変更される場合がありますので最新の料金はこちらをご確認ください。
やってみる
作成したスクリプト
今回Glueにて使用するスクリプトは以下です。
import boto3 import os import zipfile from datetime import datetime # バケット名を設定 source_bucket_name = 's3-bucket-name-A' # ファイルが格納されているバケット名 destination_bucket_name = 's3-bucket-name-B' # 保存先のバケット名 # boto3のS3クライアントを初期化 s3 = boto3.client('s3') # バケット内の全てのオブジェクトをリストアップ objects = s3.list_objects_v2(Bucket=source_bucket_name) files_to_zip = [obj['Key'] for obj in objects['Contents']] # 現在の日時を取得してファイル名を作成 now = datetime.now() zip_file_name = f"archive-{now.strftime('%Y%m%d-%H%M')}.zip" # ZIPファイルを作成 with zipfile.ZipFile(zip_file_name, 'w') as archive: for file_name in files_to_zip: # ファイルを一時的にダウンロード s3.download_file(source_bucket_name, file_name, file_name) # ZIPにファイルを追加 archive.write(file_name) # ローカルのファイルを削除 os.remove(file_name) # ZIPファイルを保存先のS3バケットにアップロード with open(zip_file_name, 'rb') as data: s3.upload_fileobj(data, destination_bucket_name, zip_file_name) # ローカルのZIPファイルを削除 os.remove(zip_file_name)
実行手順
(1) [AWS Glue] - [Data Integration and ETL] - [Jobs]より、[Python Shell script editor]をクリックし、画面右上にある[Create]ボタンをクリックします。
(2) [Script]タブの画面にて、先述のPythonコードを貼り付け、ジョブ名を変更します。
なお、S3バケット名はお手元の環境に合わせて変更してお使いください。
(3) [Job details]タブにて、IAM Roleを設定します。(無い場合は新規作成)
IAMロールには以下の権限が含まれていることを確認します。
- AmazonS3FullAccess または、使用するバケットの読み書き権限
- AWSGlueServiceRole
- AWSGlueConsoleFullAccess
(4) 設定が終わったら、画面右上[Save] および [Run]をクリックします。
(5) [Runs]タブに実行中のジョブが表示されます。
"Succeeded"と表示されていれば、正常にジョブが終了しています。
確認
今回の検証では、ソースバケットに100KBの擬似ログファイルを30個格納しました。
格納先バケットには、正常にジョブの実行時間でZipファイルが格納されていました。
圧縮はほぼ効いてなさそうですが・・・
念の為ダウンロードして解凍しましたが、問題ありません!
おわりに
Lambdaを使わずに、S3バケットにあるファイルをZip化する方法を紹介しました。
今回、検証までは行いませんでしたが、Glueの「Schedule job run」か、Amazon EventBridge Schedulerを利用することで、定期的に今回作成したジョブを実行することができます。
▼ Schedule job run
▼ Amazon EventBridge Scheduler
このエントリが誰かの助けになれば幸いです。 それでは、AWS事業本部 コンサルティング部の荒平(@0Air)がお送りしました!